package com.example.performance.engine;

import com.example.performance.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 负载测试引擎
 * 负责协调整个压测过程，管理并发用户和测试生命周期
 */
public class LoadTestEngine {

    private static final Logger logger = LoggerFactory.getLogger(LoadTestEngine.class);

    private final ExecutorService mainExecutor;
    private final ScheduledExecutorService scheduledExecutor;
    private final AtomicBoolean testRunning = new AtomicBoolean(false);
    private final AtomicInteger activeUsers = new AtomicInteger(0);

    // 测试结果收集器
    private TestReport testReport;

    // QPS限制器
    private Semaphore qpsLimiter;

    public LoadTestEngine() {
        // 创建主执行器线程池
        this.mainExecutor = Executors.newCachedThreadPool(r -> {
            Thread thread = new Thread(r);
            thread.setName("LoadTestEngine-" + thread.getId());
            thread.setDaemon(true);
            return thread;
        });

        // 创建定时任务执行器
        this.scheduledExecutor = Executors.newScheduledThreadPool(2, r -> {
            Thread thread = new Thread(r);
            thread.setName("LoadTestScheduled-" + thread.getId());
            thread.setDaemon(true);
            return thread;
        });
    }

    /**
     * 执行负载测试
     * 
     * @param config 测试配置
     * @return 测试报告
     */
    public TestReport executeLoadTest(LoadTestConfig config) {
        if (!config.isValid()) {
            throw new IllegalArgumentException("测试配置无效");
        }

        logger.info("开始执行负载测试: {}", config.getTestName());
        logger.info("测试配置: 并发用户数={}, 持续时间={}秒, 预热时间={}秒",
                config.getConcurrentUsers(), config.getTestDurationSeconds(), config.getRampUpSeconds());

        // 初始化测试报告
        testReport = new TestReport(config.getTestName());
        testRunning.set(true);

        // 初始化QPS限制器
        initQpsLimiter(config);

        try {
            // 执行测试
            executeTest(config);
        } catch (Exception e) {
            logger.error("负载测试执行失败", e);
        } finally {
            // 完成测试
            finishTest();
        }

        logger.info("负载测试完成: {}", config.getTestName());
        return testReport;
    }

    /**
     * 初始化QPS限制器
     * 
     * @param config 测试配置
     */
    private void initQpsLimiter(LoadTestConfig config) {
        if (config.getRequestsPerSecond() > 0) {
            qpsLimiter = new Semaphore(config.getRequestsPerSecond());
            // 启动QPS补充任务
            scheduledExecutor.scheduleAtFixedRate(() -> {
                if (testRunning.get()) {
                    // 每秒释放指定数量的许可证
                    int permits = config.getRequestsPerSecond() - qpsLimiter.availablePermits();
                    if (permits > 0) {
                        qpsLimiter.release(permits);
                    }
                }
            }, 1, 1, TimeUnit.SECONDS);
            logger.info("启用QPS限制: {}请求/秒", config.getRequestsPerSecond());
        }
    }

    /**
     * 执行测试
     * 
     * @param config 测试配置
     */
    private void executeTest(LoadTestConfig config) throws InterruptedException {
        // 准备并发用户任务
        List<Future<Void>> userTasks = new ArrayList<>();
        CountDownLatch startLatch = new CountDownLatch(1);

        // 创建并发用户
        for (int i = 0; i < config.getConcurrentUsers(); i++) {
            final int userId = i + 1;
            Future<Void> userTask = mainExecutor.submit(() -> {
                try {
                    // 等待所有用户准备就绪
                    startLatch.await();

                    // 预热延迟
                    if (config.getRampUpSeconds() > 0) {
                        long rampUpDelay = (long) (config.getRampUpSeconds() * 1000.0 * userId
                                / config.getConcurrentUsers());
                        if (rampUpDelay > 0) {
                            Thread.sleep(rampUpDelay);
                        }
                    }

                    activeUsers.incrementAndGet();
                    executeUserScenarios(userId, config);

                } catch (InterruptedException e) {
                    logger.debug("用户{}的测试被中断", userId);
                    Thread.currentThread().interrupt();
                } catch (Exception e) {
                    logger.error("用户{}执行失败", userId, e);
                } finally {
                    activeUsers.decrementAndGet();
                }
                return null;
            });

            userTasks.add(userTask);
        }

        // 启动所有用户
        logger.info("启动{}个并发用户", config.getConcurrentUsers());
        startLatch.countDown();

        // 等待测试时间结束
        Thread.sleep(config.getTestDurationSeconds() * 1000L);

        // 停止测试
        testRunning.set(false);
        logger.info("测试时间结束，等待用户完成当前请求...");

        // 等待所有用户完成或超时
        for (Future<Void> task : userTasks) {
            try {
                task.get(30, TimeUnit.SECONDS); // 最多等待30秒
            } catch (TimeoutException e) {
                logger.warn("用户任务超时，强制取消");
                task.cancel(true);
            } catch (ExecutionException e) {
                logger.error("用户任务执行异常", e);
            }
        }

        logger.info("所有用户已停止");
    }

    /**
     * 执行单个用户的场景
     * 
     * @param userId 用户ID
     * @param config 测试配置
     */
    private void executeUserScenarios(int userId, LoadTestConfig config) throws InterruptedException {
        ScenarioExecutor scenarioExecutor = new ScenarioExecutor();

        try {
            while (testRunning.get() && !Thread.currentThread().isInterrupted()) {
                // 执行所有启用的场景
                for (TestScenario scenario : config.getScenarios()) {
                    if (!scenario.isEnabled() || !testRunning.get()) {
                        continue;
                    }

                    // QPS限制
                    if (qpsLimiter != null) {
                        qpsLimiter.acquire(); // 获取QPS许可证
                    }

                    logger.debug("用户{}执行场景: {}", userId, scenario.getName());

                    // 执行场景
                    List<RequestResult> results = scenarioExecutor.executeScenario(scenario, config.getGlobalHeaders());

                    // 收集结果
                    for (RequestResult result : results) {
                        testReport.addResult(result);
                    }

                    // 场景间延迟
                    if (scenario.getDelayBetweenRequests() > 0) {
                        Thread.sleep(scenario.getDelayBetweenRequests());
                    }
                }
            }
        } finally {
            scenarioExecutor.shutdown();
        }
    }

    /**
     * 完成测试，生成最终报告
     */
    private void finishTest() {
        testRunning.set(false);

        if (testReport != null) {
            testReport.finishTest();
        }

        logger.info("活跃用户数: {}", activeUsers.get());
    }

    /**
     * 停止测试
     */
    public void stopTest() {
        logger.info("手动停止测试");
        testRunning.set(false);
    }

    /**
     * 关闭引擎，释放所有资源
     */
    public void shutdown() {
        logger.info("关闭负载测试引擎");

        stopTest();

        // 关闭主执行器
        if (mainExecutor != null && !mainExecutor.isShutdown()) {
            mainExecutor.shutdown();
            try {
                if (!mainExecutor.awaitTermination(15, TimeUnit.SECONDS)) {
                    logger.warn("主执行器未能在15秒内正常关闭，强制关闭");
                    mainExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                logger.warn("等待主执行器关闭时被中断");
                mainExecutor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }

        // 关闭定时执行器
        if (scheduledExecutor != null && !scheduledExecutor.isShutdown()) {
            scheduledExecutor.shutdown();
            try {
                if (!scheduledExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                    logger.warn("定时执行器未能在5秒内正常关闭，强制关闭");
                    scheduledExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                logger.warn("等待定时执行器关闭时被中断");
                scheduledExecutor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * 检查引擎状态
     * 
     * @return 引擎状态信息
     */
    public String getStatus() {
        return String.format("测试运行中: %s, 活跃用户: %d", testRunning.get(), activeUsers.get());
    }

    /**
     * 获取当前测试报告（实时）
     * 
     * @return 当前测试报告
     */
    public TestReport getCurrentReport() {
        return testReport;
    }
}